#include "tester.h"
#include "kernel/astralapi.h"

static struct AstralTickTimer timer_ins1;
static struct AstralTickTimer timer_ins2;
static struct AstralTickTimer timer_ins3;
static struct AstralTickTimer timer_contorller;

static volatile boolean done;
static int cnt1;
static int cnt2;
static int cnt3;

static void stop_test_timer(object arg)
{
    stop_ttimer(&timer_ins1);
    stop_ttimer(&timer_ins2);
    stop_ttimer(&timer_ins3);
    done = True;
}

void timeout1(object arg)
{
    cnt1++;
}
void timeout2(object arg)
{
    cnt2++;
}
void timeout3(object arg)
{
    cnt3++;
}

static void description()
{
    kprint("\n\nTick Timer Test\n"
           "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
           "3 timer with ratio 1:2:5  will be created.\n"
           "The test passed if the counter with this ratio\n\n");
}

boolean timer_test(void* arg)
{
    description();

    done = False;

    kprint("let us test the tick timer...\n");

    int waiting = 120;

    create_ttimer(&timer_contorller, waiting, stop_test_timer, &timer_ins1);
    start_ttimer(&timer_contorller);

    create_ttimer(&timer_ins1, 1, timeout1, &timer_ins1);
    set_ttimer_attribute(&timer_ins1, True, NULL);
    start_ttimer(&timer_ins1);

    create_ttimer(&timer_ins2, 2, timeout2, &timer_ins2);
    set_ttimer_attribute(&timer_ins2, True, NULL);
    start_ttimer(&timer_ins2);

    create_ttimer(&timer_ins3, 5, timeout3, &timer_ins3);
    set_ttimer_attribute(&timer_ins3, True, NULL);
    start_ttimer(&timer_ins3);

    kprint("busy wait %d ticks...\n", waiting);
    while(!done)
    {
    }

    kprint("\n\n\033[32m%10s\033[0m counts %-5d\n"
           "\033[31m%10s\033[0m counts %-5d\n"
           "\033[33m%10s\033[0m counts %-5d\n",
           "fast", cnt1, "middle", cnt2, "slow", cnt3);

    int delta1 = cnt1 - cnt2 * 2;
    int delta2 = cnt1 - cnt3 * 5;

    int diff1 = delta1*100/cnt1;
    int diff2 = delta2*100/cnt1;

    if((-10 < diff1) && (diff1 < 10))
    {
        kprint("error(fast-middle) %d(%d%%) within 10%%, accepted!\n", delta1, diff1);
    }
    else
    {
        kprint("error(fast-middle) %d(%d%%) without 10%%, \033[91mdenied\033[0m!\n", delta1, diff1);
        return False;
    }

    if((-10 < diff2) && (diff2 < 10))
    {
        kprint("error(fast-slow) %d(%d%%) within 10%%, accepted!\n", delta2, diff2);
    }
    else
    {
        kprint("error(fast-slow) %d(%d%%) without 10%%, \033[91mdenied\033[0m!\n", delta2, diff2);
        return False;
    }

    return True;
}

DEFINE_TEST(timer_test)